package route

import (
	"context"
	"fmt"
	"github.com/gogf/gf/v2/encoding/gjson"
	"github.com/gogf/gf/v2/encoding/gyaml"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gview"
)

var FILETYPEMAPPER = map[string]string{
	"json": "application/json; charset=utf-8",
	"xml":  "application/xml; charset=utf-8",
	"js":   "application/javascript; charset=utf-8",
}

type YamlCtrl struct {
}

type StaticReq struct {
	g.Meta `path:"/yaml/static" method:"post" sm:"Yaml转Json" dc:"内置配置Yaml转Json接口" tags:"Yaml" mime:"application/json"`
	Path   string `json:"path"  in:"query" v:"required" dc:"文件相对静态文件目录路径"`
}

type DynamicReq struct {
	g.Meta `path:"/yaml/dynamic" method:"post" sm:"动态配置" dc:"内置动态配置生成接口" tags:"Yaml" mime:"application/json"`
	Path   string `json:"path"  in:"query" v:"required" dc:"模版文件路径"`
	Var    string `json:"var"  in:"query" v:"required" dc:"变量路径"`
}

type DynamicBodyReq struct {
	g.Meta `path:"/yaml/dynamic/body" method:"get" sm:"动态配置" dc:"内置动态配置生成接口" tags:"Yaml"`
	Path   string `json:"path"  in:"query" v:"required" dc:"模版文件路径"`
	Var    string `json:"var"  in:"query" v:"required" dc:"变量路径"`
	Type   string `json:"type"  in:"query" v:"required" dc:"响应结果类型"`
}

type StaticRes map[string]interface{}

func (c *YamlCtrl) Static(ctx context.Context, req *StaticReq) (r *StaticRes, err error) {
	request := g.RequestFromCtx(ctx)
	// 避免与 goframe 的变量提取优先级冲突
	request.ParseQuery(req)
	var (
		obj map[string]interface{}
	)
	path := fmt.Sprintf("yaml/%s.yaml", req.Path)
	content, err := request.GetView().ParseOption(ctx, gview.Option{
		File:   path,
		Orphan: true,
	})
	if err != nil {
		return nil, err
	}
	if obj, err = gyaml.Decode([]byte(content)); err != nil {
		return nil, err
	}
	test := StaticRes(obj)
	return &test, nil
}

func (c *YamlCtrl) Dynamic(ctx context.Context, req *DynamicReq) (r *StaticRes, err error) {
	request := g.RequestFromCtx(ctx)
	// 避免与 goframe 的变量提取优先级冲突
	request.ParseQuery(req)
	var (
		tr  string
		obj g.Map
	)
	vp := ReadFile(fmt.Sprintf("resource/config/%s.yaml", req.Var))
	tp := ReadFile(fmt.Sprintf("resource/template/yaml/%s.yaml", req.Path))
	v := g.View()
	if err = gyaml.DecodeTo(vp, &obj); err != nil {
		panic(err)
	}
	if tr, err = v.ParseContent(ctx, string(tp), obj); err != nil {
		panic(err)
	}
	err = gyaml.DecodeTo([]byte(tr), obj)
	if err != nil {
		panic(err)
	}
	res := StaticRes(obj)
	return &res, nil
}

func (c *YamlCtrl) DynamicBody(ctx context.Context, req *DynamicBodyReq) (res *StaticRes, err error) {
	if FILETYPEMAPPER[req.Type] == "" {
		return nil, gerror.New("不支持的文件类型")
	}
	r := g.RequestFromCtx(ctx)
	var (
		obj g.Map
	)
	vp, err := r.GetView().ParseOption(r.Context(), gview.Option{File: fmt.Sprintf("config/%s.yaml", req.Var), Orphan: true})
	if err != nil {
		return nil, err
	}
	if err = gyaml.DecodeTo([]byte(vp), &obj); err != nil {
		return nil, err
	}
	obj["__json"], _ = gjson.EncodeString(obj)
	obj["__varpath"] = req.Var
	tr, err := r.GetView().ParseOption(r.Context(), gview.Option{File: fmt.Sprintf("yaml/%s.%s", req.Path, req.Type), Orphan: true, Params: obj})
	if err != nil {
		return nil, err
	}
	r.Response.Header().Set("Content-Type", FILETYPEMAPPER[req.Type])
	_, err = r.Response.WriteString(tr)
	return nil, err
}
